﻿module Matcher

open CssTypes
open Dom

(*
    Checks if a specific element matches a selector

*)

let matchNodeSelector (nodeSelector:NodeSelector) (elem:Element) =
    let (NodeSelector(typeSelector, qualifiers)) = nodeSelector
    let matchTagname =
        match typeSelector with
        | UniversalTypeSelector -> true
        | TypeSelector(tagName) -> elem.tagName = tagName
    let matchQualifier rule =        
        match rule with
        | AttributeExistence(name) -> elem.attributes.ContainsKey name
        | AttributeValue(name, value) -> elem.attributes.TryFind name = Some value
        | IdQualifier(idStr) -> elem.attributes.TryFind "id" = Some idStr
        | ClassQualifier(classes) ->
            match elem.attributes.TryFind "class" with
            | None -> false
            | Some classStr ->
                let attClasses = System.Text.RegularExpressions.Regex.Split(@"\s+", classStr.Trim())
                classes |> List.forall (fun cls -> attClasses |> Array.exists (fun attClass -> cls=attClass))
        | _ -> false // TODO classes etc.
    matchTagname && List.forall matchQualifier qualifiers


let rec matchSelector (selector:Selector) (elem:Element) =
    match selector with
    | SimpleSelector(nodeSelector) -> 
         matchNodeSelector nodeSelector elem
    | ContextualSelector(nodeSelector,ctxSelector) ->        
        if not (matchNodeSelector nodeSelector elem)
        then false
        else
            match ctxSelector with
            | ChildSelector(selector1) ->
                match elem.parentElement with
                | None -> false
                | Some pElement ->
                    matchSelector selector1 pElement
            | DescendentSelector(selector1) ->
                findParentMatching selector1 elem

and findParentMatching (selector:Selector) (elem:Element) =
    match elem.parentElement with
    | None -> false
    | Some parentElement ->        
        if matchSelector selector parentElement
        then true
        else findParentMatching selector parentElement
            


